package com.yami.shop.rights.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yami.shop.bean.event.ExchangeVerificationRightsEvent;
import com.yami.shop.bean.event.TransferRightsEvent;
import com.yami.shop.bean.model.QrcodeTicket;
import com.yami.shop.bean.model.User;
import com.yami.shop.bean.param.RightsParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.personnft.common.model.PersonNft;
import com.yami.shop.personnft.common.service.PersonNftService;
import com.yami.shop.rights.common.dto.VrSceneVerificationDto;
import com.yami.shop.rights.common.model.*;
import com.yami.shop.rights.common.service.*;
import com.yami.shop.rights.common.strategy.PersonRightsFactory;
import com.yami.shop.rights.common.strategy.impl.KtProdRightsStrategyImpl;
import com.yami.shop.rights.common.vo.PersonRightsVo;
import com.yami.shop.rights.common.vo.PersonnftRightsVo;
import com.yami.shop.rights.common.vo.ProdRightDetailVo;
import com.yami.shop.rights.common.vo.ProdRightsVo;
import com.yami.shop.rights.dto.VerificationRightsDto;
import com.yami.shop.security.common.bo.UserInfoInTokenBO;
import com.yami.shop.security.common.util.AuthUserContext;
import com.yami.shop.service.QrcodeTicketService;
import com.yami.shop.service.UserService;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController("rightsController")
@RequestMapping("/dtc/app/rights")
@Tag(name = "app-rights信息")
@AllArgsConstructor
public class RightsController{

    @Autowired
    private RightsVerificationUserService rightsVerificationUserService;
    @Autowired
    private ProdRightsService prodRightsService;
    @Autowired
    private PersonRightsService personRightsService;
    @Autowired
    private QrcodeTicketService qrcodeTicketService;
    @Autowired
    private PersonRightsFactory personRightsFactory;
    @Autowired
    private PersonNftService personNftService;
    @Autowired
    private UserService userService;
    @Autowired
    private RightsRecordService rightsRecordService;
    @Autowired
    private ProdRightsExchangeService prodRightsExchangeService;
    @Autowired
    private RightsTransferRecordService rightsTransferRecordService;

    @Autowired
    private KtProdRightsStrategyImpl ktProdRightsStrategyImpl;

    private final ExchangeRecordService exchangeRecordService;
    private final ApplicationEventPublisher eventPublisher;
    /**
     * 功能描述: 核销权益信息
     * @Author: LSR
     * @Date: 2023/6/9 16:24
     * @Param: externalCode 核销码，rightsId 权益ID
     */
    @GetMapping("/verificationRightsDetail")
    public ServerResponseEntity<ProdRightsVo> verificationRightsDetail(String qrCodeId){

        QrcodeTicket qrcodeTicket = qrcodeTicketService.getById(qrCodeId);
        if (qrcodeTicket == null) {
            // 二维码已过期
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.constant.code.expire"));
        }
        if (qrcodeTicket.getExpireTime() !=null
                && qrcodeTicket.getExpireTime().getTime() < System.currentTimeMillis()) {
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.constant.code.expire"));
        }
        JSONObject qrCodeData = JSONObject.parseObject(qrcodeTicket.getContent());

        // 获取权益信息
        ProdRights prodRights = prodRightsService.getById(qrCodeData.getString("rightsId"));
        // 判断该用户是否拥有核销权益信息
        boolean isVerification = rightsVerificationUserService.isVerificationRights(prodRights.getCreateAt());
        ProdRightsVo prodRightsVo = BeanUtil.copyProperties(prodRights, ProdRightsVo.class);
        prodRightsVo.setIsVerification(isVerification);
        // 获取持有人用户信息
        User userId = userService.getUserDetail(qrCodeData.getString("userId"));
        prodRightsVo.setPic(userId.getPic());
        prodRightsVo.setDtcdawAddress(userId.getDtcdawAddress());
        prodRightsVo.setNickName(userId.getNickName());
        return ServerResponseEntity.success(prodRightsVo);
    }

    /**
     * 功能描述: 核销权益 -- 线下扫码
     * @Author: LSR
     * @Date: 2023/6/9 16:48
     */
    @GetMapping("/verificationRights")
    public ServerResponseEntity<VerificationRightsDto> verificationRights(String qrCodeId){
        VerificationRightsDto verificationRightsDto = new VerificationRightsDto();
        QrcodeTicket qrcodeTicket = qrcodeTicketService.getById(qrCodeId);
        if (qrcodeTicket == null) {
            // 二维码已过期
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.constant.code.expire"));
        }
        if (qrcodeTicket.getExpireTime() !=null
                && qrcodeTicket.getExpireTime().getTime() < System.currentTimeMillis()) {
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.constant.code.expire"));
        }
        JSONObject qrCodeData = JSONObject.parseObject(qrcodeTicket.getContent());
        // 判断权益是否有效
        ProdRights byId = prodRightsService.getById(qrCodeData.getString("rightsId"));
        if(ObjectUtil.isEmpty(byId) || byId.getStatus() != 1){
            throw new YamiShopBindException("无效权益信息");
        }
        // 判断剩余次数
        Long personRightsId = personRightsFactory.getSurplusTimes(qrCodeData.getLongValue("personRightsId"), byId.getType());
        if(personRightsId < 1){
            throw new YamiShopBindException("权益已使用");
        }
        // 判断持有人
        PersonNft personNft = new PersonNft();
        personNft.setTokenId(qrCodeData.getString("tokenId"));
        List<PersonNft> personNfts =
                personNftService.listByParam(personNft);
        List<PersonNft> collect = personNfts.stream().filter(s -> s.getStatus() != 0).collect(Collectors.toList());
        if(collect.size() > 0){
            throw new YamiShopBindException("作品状态异常，无法核销");
        }
        if(ObjectUtil.isEmpty(personNfts) || !ObjectUtil.equal(personNfts.get(0).getUserId(),qrCodeData.getString("userId"))){
            throw new YamiShopBindException("权益归属异常");
        }
        // 核销次数
        qrCodeData.put("count",1);
        // 核销权益
        personRightsFactory.verificationRights(qrCodeData);
        verificationRightsDto.setCreateTime(new Date());
        return ServerResponseEntity.success(verificationRightsDto);
    }

    /**
     * 功能描述: 可核销权益详细信息
     * @Author: LSR
     * @Date: 2023/6/12 11:30
     */
    // 当前版本 一个 权益绑定一个券 如 多个券 加参数
    @GetMapping("/getProdRightsById")
    public ServerResponseEntity<ProdRightsVo> getProdRightsById(Long personRightsId){
        String userId = AuthUserContext.get().getUserId();
        ProdRightsVo prodRightsVo = personRightsService.getProdRightsById(personRightsId,userId);
        return ServerResponseEntity.success(prodRightsVo);
    }

    // 通过token获取 优先购权益信息 ---  DTC
    @GetMapping("/getQualification")
    public ServerResponseEntity<List<PersonRightsVo>> getQualification(String tokenId){
        List<PersonRightsVo> personRightsVos = personRightsService.getPersonRightsByRightsId(tokenId);
        return ServerResponseEntity.success(personRightsVos);
    }


    // 通过PersonRightsId获取 优先购权益信息 ---  微发行
    @GetMapping("/getQualificationByPersonRightsId")
    public ServerResponseEntity<List<PersonRightsVo>> getQualificationByPersonRightsId(Long personRightsId){
        List<PersonRightsVo> personRightsVos = personRightsService.getPersonRightsByPersonRightsId(personRightsId);
        return ServerResponseEntity.success(personRightsVos);
    }



    @GetMapping("/getRightsLists")
    public ServerResponseEntity<IPage<ProdRightDetailVo>> getRightsLists(PageParam<ProdRightDetailVo> page){
        IPage<ProdRightDetailVo> list = personRightsFactory.getRightsLists(page);
        return ServerResponseEntity.success(list);
    }

    /**
     *
     * @param page
     * @param status 0 未使用 1 使用 3 过期
     * @return
     */
    @GetMapping("/getNoUseRightsLists")
    public ServerResponseEntity<IPage<ProdRightDetailVo>> getNoUseRightsLists(PageParam<ProdRightDetailVo> page,Integer status){
        String userId = AuthUserContext.get().getUserId();
        IPage<ProdRightDetailVo> list = personRightsFactory.getNoUseRightsLists(page,status,userId);
        return ServerResponseEntity.success(list);
    }


    /**
     * 根据商品Id获取持仓权益
     * @param page
     * @param rightsParam
     * @return
     */
    @GetMapping("/getRightsByProdId")
    public ServerResponseEntity<IPage<ProdRights>> getRightsByProdId(PageParam<ProdRights> page, @ParameterObject RightsParam rightsParam){
        IPage<ProdRights> list = personRightsFactory.getPersonRightsByProId(page,rightsParam);
        return ServerResponseEntity.success(list);
    }


    /**
     * 获取实物兑换商品详情
     * @param personRightsId
     * @return
     */
    @GetMapping("/getProdInfoByPersonRightsId")
    public ServerResponseEntity<ProdRightsVo> getProdInfoByPersonRightsId(Long personRightsId){
        ProdRightsVo prodRightsVo = personRightsService.getProdInfoByPersonRightsId(personRightsId);
        return ServerResponseEntity.success(prodRightsVo);
    }

    /**
     * 功能描述: 实物核销权益发物流--线上提货
     * @Author: LSR
     * @Date: 2023/6/9 16:48
     */
    @GetMapping("/verificationExchangeRights")
    public ServerResponseEntity<VerificationRightsDto> verificationExchangeRights(Long personRightsId,Long addressId){
        VerificationRightsDto verificationRightsDto = new VerificationRightsDto();
        String userId = AuthUserContext.get().getUserId();
        if (RedisUtil.hasKey("verificationExchangeRights::"+personRightsId)) {
           throw new YamiShopBindException("正在操作，请稍等");
        }
        RedisUtil.set("verificationExchangeRights::"+personRightsId,personRightsId,10);
        PersonnftRightsVo prodRightsById = personRightsService.getProdRightsInfoById(personRightsId);
        // 判断权益是否有效
        ProdRights byId = prodRightsService.getById(prodRightsById.getRightsId());
        if(ObjectUtil.isEmpty(byId) || byId.getStatus() != 1){
            throw new YamiShopBindException("无效权益信息");
        }
        // 判断剩余次数
        Long personRightsIdtimes = personRightsFactory.getSurplusTimes(Long.valueOf(prodRightsById.getPersonRightsId()), byId.getType());
        if(personRightsIdtimes < 1){
            throw new YamiShopBindException("权益已使用");
        }
        // 判断持有人
        PersonNft personNft = new PersonNft();
        personNft.setTokenId(prodRightsById.getTokenId());
        List<PersonNft> personNfts =
                personNftService.listByParam(personNft);
        List<PersonNft> collect = personNfts.stream().filter(s -> s.getStatus() != 0).collect(Collectors.toList());
        if(collect.size() > 0){
            throw new YamiShopBindException("作品状态异常，无法核销");
        }
        if(ObjectUtil.isEmpty(personNfts) || !ObjectUtil.equal(personNfts.get(0).getUserId(),userId)){
            throw new YamiShopBindException("权益归属异常");
        }
        List<ProdRightsExchange> rightsProds = prodRightsExchangeService.list(new QueryWrapper<ProdRightsExchange>().eq("rights_id", prodRightsById.getRightsId()).eq("status", 1).eq("blind_type", "1"));
        //添加核销事件
        eventPublisher.publishEvent(new ExchangeVerificationRightsEvent(Long.valueOf(prodRightsById.getPersonRightsId()),rightsProds.get(0).getBlindId(),addressId));
        verificationRightsDto.setCreateTime(new Date());
        return ServerResponseEntity.success(verificationRightsDto);
    }

    /**
     * 确认收货
     */
    @GetMapping("/updateStatusByOrderNumber")
    public ServerResponseEntity<ProdRightsVo> updateStatusByPersonRightsId(String OrderNumber){
        exchangeRecordService.updateStatusByPersonRightsId(OrderNumber);
        return ServerResponseEntity.success();
    }

    /**
     * 根据持仓选一id获取兑换记录
     */
    @GetMapping("/getExchangeRecordByPersonRightsId")
    public ServerResponseEntity<ExchangeRecord> getExchangeRecordByPersonRightsId(Long personRightsId){
        ExchangeRecord one = exchangeRecordService.getOne(new LambdaQueryWrapper<ExchangeRecord>().eq(ExchangeRecord::getPersonRightsId, personRightsId));
        return ServerResponseEntity.success(one);
    }

    /**
     * 权益转移
     */
    @GetMapping("rightsTransfer")
    public ServerResponseEntity<Void> rightsTransfer(Long personRightsId,String receiveUserId){
        //查询该权益是否支持转移
        UserInfoInTokenBO userInfoInTokenBO = AuthUserContext.get();
        PersonRights one = personRightsService.getById(personRightsId);
        if(ObjectUtil.isNotEmpty(one.getTokenId())){
            return ServerResponseEntity.showFailMsg("该权益不支持转赠");
        }
        if(one.getStatus() != 0){
            return ServerResponseEntity.showFailMsg("权益状态异常");
        }
        // 冻结权益信息
        one.setStatus(4);
        personRightsService.updateById(one);
        // 新增转移信息
        RightsTransferRecord rightsTransferRecord = new RightsTransferRecord();
        rightsTransferRecord.setPersonRightsId(personRightsId);
        rightsTransferRecord.setHaveUser(userInfoInTokenBO.getUserId());
        rightsTransferRecord.setReceiveUser(receiveUserId);
        rightsTransferRecord.setStatus(1);
        rightsTransferRecordService.save(rightsTransferRecord);

        return ServerResponseEntity.success();
    }

    /**
     * 权益领取
     */
    @GetMapping("rightsReceive")
    public ServerResponseEntity<Void> rightsReceive(Long personRightsId,Integer status){
        UserInfoInTokenBO userInfoInTokenBO = AuthUserContext.get();
        // 查询权益状态
        PersonnftRightsVo personRights = personRightsService.getProdRightsInfoById(personRightsId);
        if(personRights.getStatus() != 4){
            return ServerResponseEntity.showFailMsg("权益状态异常");
        }
        QueryWrapper<RightsTransferRecord> rightsTransferRecordQueryWrapper = new QueryWrapper<>();
        rightsTransferRecordQueryWrapper.eq("person_rights_id",personRightsId);
        rightsTransferRecordQueryWrapper.eq("receive_user",userInfoInTokenBO.getUserId());
        rightsTransferRecordQueryWrapper.eq("status",1);
        RightsTransferRecord one = rightsTransferRecordService.getOne(rightsTransferRecordQueryWrapper);
        if(ObjectUtil.isEmpty(one)){
            return ServerResponseEntity.showFailMsg("权益领取记录异常");
        }
        // 拒绝
        if(status == 0){
            one.setStatus(3);
            rightsTransferRecordService.updateById(one);
            return ServerResponseEntity.success();
        }
        // 权益领取转移
        TransferRightsEvent transferRightsEvent =
                TransferRightsEvent.builder()
                        .rightsTransferRecordId(one.getId())
                        .personRightsType(personRights.getType())
                        .haveUser(one.getHaveUser())
                        .receiveUser(one.getReceiveUser())
                        .rightsId(personRights.getRightsId())
                        .build();
        personRightsFactory.rightsTransfer(transferRightsEvent);

        return ServerResponseEntity.success();
    }

    /**
     * 场景权益核销
     */
    @PostMapping("vrSceneVerification")
    public ServerResponseEntity<Void> vrSceneVerification(@RequestBody VrSceneVerificationDto vrSceneVerificationDto){
        // TODO 校验抽奖次数
        UserInfoInTokenBO userInfoInTokenBO = AuthUserContext.get();
        // 查询权益类型
        ProdRights prodRights = prodRightsService.getById(vrSceneVerificationDto.getRightsId());
        if(prodRights.getType().equals("11")){
            ktProdRightsStrategyImpl.rightsKtProd(
                    Long.valueOf(vrSceneVerificationDto.getProdId()),
                    vrSceneVerificationDto.getBlindType(),
                    userInfoInTokenBO.getUserId(),
                    prodRights.getCreateAt()
                    ,vrSceneVerificationDto.getRightsId());

        }

        return ServerResponseEntity.success();
    }
}
